package com.cskaoyan.javase.oop3.innerclazz6.anonymous;

/**
 * @description: 匿名内部类
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 匿名内部类：是匿名的（局部）内部类，也就是说匿名内部类本质上是局部内部类
 * 匿名对象：没有名字的对象
 * 匿名内部类：没有名字的（局部）内部类
 *
 * 匿名内部类的使用优缺点：
 * ​	1，当我们只使用一次某类或者某接口的子类对象时，使用匿名内部类，会稍微方便一点
 * ​	2，如果需要多次访问子类对象的成员，匿名内部类很麻烦。
 * ​	3，如果访问匿名子类中的独有方法，必须用匿名对象去访问
 *
 *
 */
public class Demo {
    public static void main(String[] args) {
        //老花样：创建接口的实现类
        I i = new IA();
        i.test();

        //新花样：局部内部类创建接口实现类
        class InnerLocalClazz implements I{
            @Override
            public void test() {
                System.out.println("高端的写法，总是这么朴实无华，枯燥！");
            }
        }
        //直接创建局部内部类对象
        InnerLocalClazz innerLocalClazz = new InnerLocalClazz();
        innerLocalClazz.test();

        //新新花样：在局部内部类的基础上，我干脆连你这个内部类我都不要了，直接创建局部内部类对象，也就是匿名局部类
        //语法： 直接创建对象： new 接口或者类(){};
        //方式一
        I i2 = new I() {
            @Override
            public void test() {
                System.out.println("我是匿名内部类对象中的test方法");
            }

            public void test2(){

            }
        };//new加上后面一块就是对象，可以用父类去接收它。实际上想接收 也只能用父类去接收
        i2.test();
        //i2.test2();  因为编译看左边，所以调用不了子类独有方法
        //((I) i2).test2(); //因为这个子类是匿名的，也没有办法强转它
        //总结，这种方式 打死了 也访问不了子类的独有方法

        //方式二
        //以上匿名内部类的对象也可以不接收
        new I(){
            @Override
            public void test() {
                System.out.println("不用父类接收");
            }public void test2() {
                System.out.println("子类独有");
            }
        }.test2();

        //以上两种方式，各有什么优缺点
        //方式一用接口去接收后，这个对象就有引用，可以反复使用，但是方式一是用父类引用去接收的，这样就用不了子类中独有的方法
        //方式二没有去接收，这个对象没有引用，只能用一次，用完后就成为垃圾了。但是方式二 可以调用子类独有方法
        //方式一 方式二如果都能用 优先使用方式二 因为方式二省事


        //用匿名内部类创建类的子类
        //语法：new 类(){};
        new A(){
            @Override
            public void test() {
                System.out.println("我是普通类的匿名内部类子类对象");
            }
        }.test();

        System.out.println(new AbstractA() {
            @Override
            public int test() {
                return 10;
            }
        }.test());
//这一块相当于就是10 所以就可以对他进行 10 的操作 比如赋值 比如计算 比如打印

        A a = new A() {
        }; //它如果能够做自己，那它到底是什么类型呢？ 如果它做儿子，还能用父类来接收 隐含的继承
    }
}
interface I{
    void test();
}
class IA implements I{
    @Override
    public void test() {
        System.out.println("我是IA I接口的实现类");
    }
}
class A{
    public void test(){}
}
abstract class AbstractA{
    public abstract int test();
}